package com.sagframe.sagacity.sqltoy.plus.multi;

import com.sagframe.sagacity.sqltoy.plus.*;
import com.sagframe.sagacity.sqltoy.plus.conditions.AbstractWrapper;
import com.sagframe.sagacity.sqltoy.plus.conditions.ISqlSegment;
import com.sagframe.sagacity.sqltoy.plus.conditions.eumn.SqlKeyword;
import com.sagframe.sagacity.sqltoy.plus.FiledValueFilterStrategy;
import com.sagframe.sagacity.sqltoy.plus.conditions.segments.MergeSegments;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

public abstract class AbstractMultiWrapper<Children extends AbstractMultiWrapper<Children>> implements MultiWrapper {

    protected final Children typedThis = (Children)this;

    protected MultiContext context;

    protected MergeSegments expression;

    protected MultiISqlAssemble sqlAssemble;

    public AbstractMultiWrapper(Class<?> toClass) {
        this.context = new MultiContext(toClass, new HashMap<>(), new ArrayList<>());
        this.expression = new MergeSegments();
        this.sqlAssemble = new MultiISqlAssemble();
    }

    public AbstractMultiWrapper(MultiContext context) {
        this.context = context;
        this.expression = new MergeSegments();
        this.sqlAssemble = new MultiISqlAssemble();
    }

    public <T> Class<T> toClass() {
        return (Class<T>)context.toClass;
    }

    /**
     * 内部自用
     * <p>NOT 关键词</p>
     */
    protected Children not(boolean condition) {
        return addAssembler((mappingStrategy -> {
            maybeDo(condition, () -> appendSqlSegments(SqlKeyword.NOT));
        }));
    }

    @Override
    public void assemble(MultiFiledMappingStrategy mappingStrategy) {
        context.assemble(mappingStrategy);
    }

    @Override
    public String getSqlSegment() {
        return context.getSqlSegment();
    }

    @Override
    public Map<String, Object> getSqlSegmentParamMap() {
        return context.getSqlSegmentParamMap();
    }

    /**
     * 创建sql组装器
     * @param sqlAssembler
     *               -组装器具体实现
     * @return
     *               -返回自身
     */
    protected Children addAssembler(MultiISqlAssembler sqlAssembler) {
        if (sqlAssembler != null) {
            sqlAssemble.add(sqlAssembler);
        }
        return typedThis;
    }

    protected final Children maybeDo(boolean condition, AbstractWrapper.DoSomething something) {
        if (condition) {
            something.doIt();
        }
        return typedThis;
    }

    /**
     * 添加 where 片段
     *
     * @param sqlSegments ISqlSegment 数组
     */
    protected void appendSqlSegments(ISqlSegment... sqlSegments) {
        expression.add(sqlSegments);
    }

    protected void setLastSql(String lastSql) {
        expression.setLastSql(lastSql);
    }

    protected boolean validateFiledValue(Object value) {
        return FiledValueFilterStrategy.FiledValueFilterStrategyHolder.getInstance().validate(value);
    }

    /**
     * 获取condition的sql片段对象
     * @param mappingStrategy
     * @return
     */
    public ISqlSegment getISqlSegment(MultiFiledMappingStrategy mappingStrategy) {
        if (sqlAssemble.isEmpty()) {
            return null;
        }
        sqlAssemble.assemble(mappingStrategy);
        String conditionSql = expression.getSqlSegment();
        if (conditionSql != null && !conditionSql.isEmpty()) {
            return new ISqlSegment() {
                @Override
                public String getSqlSegment() {
                    return conditionSql;
                }
                public Map<String, Object> getSqlSegmentParamMap() {
                    return expression.getSqlSegmentParamMap();
                }
            };
        }
        return null;
    }
}
